#ifndef V4L2_VIDEO_LIBRARY_H
#define V4L2_VIDEO_LIBRARY_H

#include <map>
#include <string>
#include <vector>
#include <functional>
#include <atomic>
#include <linux/videodev2.h>

//first: width, second: height
using Resolution = std::pair<uint32_t, uint32_t>;
//描述帧缓冲区
struct FrameBuffer
{
    unsigned short* start; //帧缓冲区起始地址
    unsigned long length; //帧缓冲区长度
};

using ImageProcessCallback = std::function<void(std::string&)>;
using ImgProcessCallback = std::function<void(unsigned char*, int)>;


class CV4L2Video
{
public:
    explicit CV4L2Video(const char* device_name);
    ~CV4L2Video();
    /*
     * @brief:打开摄像头
     * @param:无
     * @return:成功返回true，失败返回false
     */
    bool open_video();
    /*
     * @brief:关闭摄像头
     * @param:无
     * @return:成功返回true，失败返回false
     */
    void close_video();
    /*
     * @brief:判断摄像头是否为捕获模式
     * @param:无
     * @return:是返回true，不是返回false
     */
    [[nodiscard]] bool is_capture() const;
    /*
     * @brief: 枚举摄像头支持的像素格式
     * @param: uint32_t pixel_format: 像素格式
     * @param: const std::string& desc: 描述
     * @return: 无
     */
    void enum_video_pixel_format(std::vector<std::string>& fmt) const;
    /*
     * @brief: 枚举摄像头支持的分辨率
     * @param: std::vector<std::string>& fm_size:能够支持的所有的分辨率
     * @return: 无
     */
    void enum_video_frame_size(std::vector<Resolution>& fm_size) const;
    /*
     * @brief: 枚举摄像头支持的帧率
     * @param: std::vector<std::string>& fm_interval:能够支持的所有的帧率
     * @return: 无
     */
    void enum_video_frame_interval(std::vector<uint32_t>& fps) const;
    /*
     * @brief: 设置摄像头参数
     * @param: uint32_t pixel_format: 像素格式
     * @param: Resolution resolution: 分辨率
     * @param: uint32_t fps: 帧率
     * @return: 成功返回true，失败返回false
     */
    [[nodiscard]] bool set_video_parameter(uint32_t pixel_format, Resolution resolution, uint32_t fps) const;
    /*
     * @brief: 开始捕获视频
     * @param: 无
     * @return: 成功返回true，失败返回false
     */
    [[nodiscard]] bool start_capture() const;
    /*
     * @brief: 停止捕获视频
     * @param: 无
     * @return: 成功返回true，失败返回false
     */
    [[nodiscard]] bool stop_capture() const;
    /*
     * @brief: 获取一帧图像
     * @param: std::string& img: 图像数据
     * @return: 成功返回0，失败返回-1
     */
    void get_frame_image(std::string& img, const ImageProcessCallback& func = nullptr) const;
    /*
     * @brief: 获取一帧图像
     * @param: std::string& img: 图像数据
     * @return: 成功返回0，失败返回-1
     */
    void get_frame_image(unsigned char* img_buf, int len, const ImgProcessCallback& func = nullptr) const;
    /*
     * @brief: 读取一帧数据
     * @param: 一帧图片数据
     * @return: A/N
     */
    void read(std::string& img);
    /*
     * @brief: 分配内存
     * @param: 无
     */
    int v4l2_malloc_buffer(int frame_num = DEFAULT_FRAME_NUM_);
    int v4l2_free_buffer();
private:
    void get_video_pixel_format(std::vector<uint32_t>& pixel_fmt) const;
    void get_video_pixel_frame_size(std::map<uint32_t, std::vector<Resolution>>& fm_size) const;
    static constexpr int DEFAULT_FRAME_NUM_ = 3;
    std::array<FrameBuffer, DEFAULT_FRAME_NUM_> frame_buffer_{};
    //static std::string to_image(void* data, size_t size);
    std::atomic_bool init_flag_{false};
    v4l2_buffer v4l2_buf_{};
    std::string device_name_;
    int dev_fd_;
};



#endif //V4L2_VIDEO_LIBRARY_H